package com.ruoyi.file.controller;

import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.exception.ServiceException;
import com.ruoyi.file.service.CheckSignService;
import com.ruoyi.file.service.FileService;
import com.ruoyi.file.utils.FileUploadUtils;
import com.ruoyi.file.utils.UploadFileService;
import com.ruoyi.system.api.domain.SysFile;
import com.ruoyi.system.api.factory.RemoteFileFallbackFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
import java.io.File;
import java.io.IOException;
import java.util.List;

@RequestMapping("file")
@RestController
public class UploadController {
    private static final Logger log = LoggerFactory.getLogger(RemoteFileFallbackFactory.class);
    @Autowired
    private CheckSignService checkSignService;
    @Autowired
    private FileService fileService;
    @Autowired
    private UploadFileService uploadFileService;

    //允许服务器间有30分钟的延时
    private int delay = 1800;

    @PostMapping("/upload/{appId}/{ts}/{sign}")
    public R<String> upload(HttpServletRequest request,
                            @PathVariable String appId,
                            @PathVariable long ts,
                            @PathVariable String sign) {
        long now = System.currentTimeMillis() / 1000;
        log.info("({}) upload begin", now);
        if (Math.abs(ts - now) > delay) {
            log.warn("Request invalid：{}<->{}", appId, ts);
            return R.fail("Request invalid!");
        }
        if (!checkSignService.checkSign(appId, ts, sign)) {
            log.warn("check sign fail：{}<->{}<->{}", appId, ts, sign);
            return R.fail("check sign fail");
        }
        SysFile fileId = fileService.save(checkSignService.getAppTag(appId), request);
        log.info("({}) upload end:{}", now, fileId);
        return fileId == null ? R.fail("上传失败") : R.ok(fileId.getFileId());
    }

    @PostMapping("/upload4Url/{appId}/{ts}/{sign}")
    public R<SysFile> upload4Url(HttpServletRequest request,
                            @PathVariable String appId,
                            @PathVariable long ts,
                            @PathVariable String sign) {
        long now = System.currentTimeMillis() / 1000;
        log.info("({}) upload begin", now);
        if (Math.abs(ts - now) > delay) {
            log.warn("Request invalid：{}<->{}", appId, ts);
            return R.fail("Request invalid!");
        }
        if (!checkSignService.checkSign(appId, ts, sign)) {
            log.warn("check sign fail：{}<->{}<->{}", appId, ts, sign);
            return R.fail("check sign fail");
        }
        SysFile fileId = fileService.save(checkSignService.getAppTag(appId), request);
        log.info("({}) upload end:{}", now, fileId);
        return fileId == null ? R.fail("上传失败") : R.ok(fileId);
    }

    @GetMapping("/view/{fileId}")
    public void view(HttpServletRequest request, HttpServletResponse response,
                     @PathVariable String fileId,
                     @RequestParam("appId") String appId,
                     @RequestParam("timestamp") long ts,
                     @RequestParam("expires") long expires,
                     @RequestParam("sign") String sign,
                     String name) throws ServletException, IOException {
        log.info("/view/{}", fileId);
        String app = checkSignService.getAppTag(appId);
        if (!new File(fileService.getFilePath(app, fileId)).exists()) {
//            request.getRequestDispatcher("/view-next/" + fileId).forward(request, response);
            response.setStatus(403);
            return;
        }
        this.viewOld(request, response, fileId, appId, ts, expires, sign, name);
    }


    @GetMapping("/deleteFile/{appId}/{ts}/{sign}")
    public R<Boolean> deleteFile( @RequestParam String[] fileIds,
                                  @PathVariable String appId,
                                  @PathVariable long ts,
                                  @PathVariable String sign
                        ) throws ServletException, IOException {
        log.info("/deleteFile/{}", fileIds);
        if(fileIds== null|| fileIds.length==0){
            return R.fail("没有该文件");
        }
        String app = checkSignService.getAppTag(appId);
        if (!checkSignService.checkSign(appId, ts, sign)) {
            log.warn("check sign fail：{}<->{}<->{}", appId, ts, sign);
            return R.fail("check sign fail");
        }
        return R.ok(fileService.deleteFile(fileIds, checkSignService.getAppTag(appId)));
    }

    @GetMapping("/view-old/{fileId}")
    public void viewOld(HttpServletRequest request, HttpServletResponse response,
                        @PathVariable String fileId,
                        @RequestParam("appId") String appId,
                        @RequestParam("timestamp") long ts,
                        @RequestParam("expires") long expires,
                        @RequestParam("sign") String sign,
                        String name) {
        log.info("/view-old/{}", fileId);
        this.download(request, response, fileId, appId, ts, expires, sign, name, true);
    }

    @GetMapping("/download/{fileId}")
    public void download(HttpServletRequest request, HttpServletResponse response,
                         @PathVariable String fileId,
                         @RequestParam("appId") String appId,
                         @RequestParam("timestamp") long ts,
                         @RequestParam("expires") long expires,
                         @RequestParam("sign") String sign,
                         String name) {
        log.info("/download/{}", fileId);
        this.download(request, response, fileId, appId, ts, expires, sign, name, false);
    }

    private void download(HttpServletRequest request, HttpServletResponse response,
                          String fileId,
                          String appId,
                          long ts,
                          long expires,
                          String sign,
                          String name,
                          boolean isOnline) {
        long now = System.currentTimeMillis() / 1000;
        if (ts - now > delay || ts + expires < now) {
            log.warn("Request invalid：{}<->{}<->{}", appId, ts, expires);
            response.setStatus(403);
            return;
        }
        if (!checkSignService.checkSign(appId, ts, fileId, expires, sign)) {
            log.warn("check sign fail：{}<->{}<->{}<->{}", appId, ts, expires, sign);
            response.setStatus(403);
            return;
        }
        fileService.download(checkSignService.getAppTag(appId), fileId, name, isOnline, request, response);
    }

}